home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / bash / bash_108 / bash-108.zoo / src / ulimit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-12  |  9.8 KB  |  456 lines

  1. /* ulimit.c -- Setting resource usage for children of the shell. */
  2.  
  3. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU Bash, the Bourne Again SHell.
  6.  
  7. Bash is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 1, or (at your option) any later
  10. version.
  11.  
  12. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with Bash; see the file COPYING.  If not, write to the Free Software
  19. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include <stdio.h>
  22. #include <sys/types.h>
  23. #include <sys/param.h>
  24. #include <errno.h>
  25. #include "shell.h"
  26.  
  27. extern int errno;
  28.  
  29. #if defined (HAVE_RESOURCE)
  30. #include <sys/time.h>
  31. #include <sys/resource.h>
  32. /**
  33.  ** We require some library support on the Atari ST
  34.  **/
  35. #if defined(atarist)
  36. #include "../lib+/r-res.h"
  37. #endif
  38. #else
  39. #include <sys/times.h>
  40. #endif
  41.  
  42. #if defined (_POSIX_VERSION)
  43. #include <limits.h>
  44. #endif
  45.  
  46. /* Check for the most basic synbols.  If they aren't present, this
  47.    system's <sys/resource.h> isn't very useful to us. */
  48. #if !defined RLIMIT_FSIZE
  49. #  undef HAVE_RESOURCE
  50. #endif
  51.  
  52. /* **************************************************************** */
  53. /*                                    */
  54. /*            Ulimit builtin and Hacks.               */
  55. /*                                    */
  56. /* **************************************************************** */
  57.  
  58. /* Block size for ulimit operations. */
  59. #define ULIMIT_BLOCK_SIZE ((long)1024)
  60.  
  61. #define u_FILE_SIZE 1
  62. #define u_MAX_BREAK_VAL 3
  63. #define u_PIPE_SIZE 4
  64. #define u_CORE_FILE_SIZE 6
  65. #define u_DATA_SEG_SIZE 8
  66. #define u_PHYS_MEM_SIZE 10
  67. #define u_CPU_TIME_LIMIT 12
  68. #define u_STACK_SIZE 14
  69. #define u_NUM_OPEN_FILES 16
  70.  
  71. #ifndef RLIM_INFINITY
  72. #define RLIM_INFINITY  0x7fffffff
  73. #endif
  74.  
  75. static long pipesize ();
  76.  
  77. /* Report or set limits associated with certain per-process resources.
  78.    See the help documentation in builtins.c for a full description.
  79.    Chet Ramey & Brian Fox 3/13/89. */
  80. ulimit_builtin (list)
  81.      register WORD_LIST *list;
  82. {
  83.   long shell_ulimit ();
  84.   register char *s;
  85.   int c, setting, cmd, r = EXECUTION_SUCCESS;
  86.   long current_limit, real_limit, limit = -1L;
  87.   long block_factor;
  88.  
  89.   do
  90.     {
  91.       cmd = u_FILE_SIZE;
  92.       setting = 0;
  93.       block_factor = ULIMIT_BLOCK_SIZE;
  94.  
  95.       if (list)
  96.     {
  97.       s = list->word->word;
  98.       if (s && (*s == '-'))
  99.         {
  100.           c = *++s;
  101.  
  102.           if (!c || *++s)
  103.         goto error_case;
  104.  
  105.           list = list->next;
  106.  
  107.           switch (c)
  108.         {
  109.         case 'f':
  110.           cmd = u_FILE_SIZE;
  111.           break;
  112.  
  113. #if defined (HAVE_RESOURCE)
  114.         case 'a':
  115.           print_all_limits ();
  116.           return (EXECUTION_SUCCESS);
  117.  
  118.         case 'c': cmd = u_CORE_FILE_SIZE;
  119.           break;
  120.  
  121.         case 'd': cmd = u_DATA_SEG_SIZE;
  122.           break;
  123.  
  124.         case 'm': cmd = u_PHYS_MEM_SIZE;
  125.           break;
  126.  
  127.         case 't':
  128.           cmd = u_CPU_TIME_LIMIT;
  129.           block_factor = 1;    /* seconds */
  130.           break;
  131.  
  132.         case 's':
  133.           cmd = u_STACK_SIZE;
  134.           break;
  135.  
  136.         case 'p':
  137.           cmd = u_PIPE_SIZE;
  138.           block_factor = 512;
  139.           break;
  140.  
  141.         case 'n':
  142.           cmd = u_NUM_OPEN_FILES;
  143.           block_factor = 1;
  144.           break;
  145.  
  146. #endif /* HAVE_RESOURCE */
  147.         default:
  148.         error_case:
  149. #if ! defined (HAVE_RESOURCE)
  150.           builtin_error("usage: ulimit [-f] [new limit]");
  151. #else
  152.           builtin_error("usage: ulimit [-acmdstfpn] [new limit]");
  153. #endif
  154.           return EXECUTION_FAILURE;
  155.         }
  156.         }
  157.       
  158.       /* If an argument was supplied for the command, then we want to
  159.          set the limit. */
  160.       if (list)
  161.         {
  162.           s = list->word->word;
  163.           list = list->next;
  164.           if (sscanf (s, "%ld", &limit) != 1)
  165.         {
  166.           if (strcmp (s, "unlimited") == 0)
  167.             limit = RLIM_INFINITY;
  168.           else
  169.             {
  170.               builtin_error ("bad non-numeric arg `%s'", s);
  171.               return (EXECUTION_FAILURE);
  172.             }
  173.         }
  174.           setting++;
  175.         }
  176.     }
  177.  
  178.       if (limit == RLIM_INFINITY)
  179.     block_factor = 1;
  180.  
  181.       real_limit = limit * block_factor;
  182.  
  183.       current_limit = shell_ulimit (cmd, real_limit, 0);
  184.  
  185.       if (setting)
  186.     {
  187. #if !defined (HAVE_RESOURCE)
  188.       if ((current_limit < (real_limit)) && (getuid() != 0))
  189.         {
  190.           builtin_error ("cannot raise limit");
  191.           return (EXECUTION_FAILURE);
  192.         }
  193. #endif
  194.  
  195.         if (shell_ulimit (cmd, real_limit, 1) == -1)
  196.           {
  197.         builtin_error ("cannot raise limit: %s", strerror(errno));
  198.         r = EXECUTION_FAILURE;
  199.           }
  200.         else
  201.           r = EXECUTION_SUCCESS;
  202.  
  203.         return (r);
  204.     }
  205.       else
  206.     {
  207.       if (current_limit != RLIM_INFINITY)
  208.         printf ("%ld\n", (current_limit / block_factor));
  209.       else
  210.         printf ("unlimited\n");
  211.     }
  212.     }
  213.   while (list);
  214.  
  215.   return (EXECUTION_SUCCESS);
  216. }
  217.  
  218. /* The ulimit that we call from within Bash.  Extended to handle
  219.    more resources by Chet Ramey (chet@cwjcc.cwru.edu).
  220.    WHICH says which limit to twiddle; SETTING is non-zero if NEWLIM
  221.    contains the desired new limit.  Otherwise, the existing limit is
  222.    returned. */
  223. long
  224. shell_ulimit (which, newlim, setting)
  225.      int which, setting;
  226.      long newlim;
  227. {
  228. #if defined (HAVE_RESOURCE)
  229.   struct rlimit limit;
  230. #endif
  231.  
  232.   switch (which)
  233.     {
  234.  
  235.     case u_FILE_SIZE:
  236.       if (!setting)
  237.     {
  238. #if !defined (HAVE_RESOURCE)
  239.       /* ulimit () returns a number that is in 512 byte blocks, thus  we
  240.          must multiply it by 512 to get back to bytes.  This is false
  241.          only under HP/UX 6.x. */
  242.       long result;
  243.  
  244.       result = ulimit (1, 0l);
  245.  
  246. #if defined (hpux) && !defined (_POSIX_VERSION)
  247.       return (result);
  248. #else
  249.       return (result * 512);
  250. #endif /* Hpux 6.x */
  251. #else
  252.       if (getrlimit (RLIMIT_FSIZE, &limit) != 0)
  253.         return ((long) -1);
  254.       return (limit.rlim_cur);
  255. #endif
  256.     }
  257.       else
  258.     {
  259. #if !defined (HAVE_RESOURCE)
  260.       return (ulimit (2, newlim / 512L));
  261. #else
  262.       getrlimit (RLIMIT_FSIZE, &limit);
  263.       limit.rlim_cur = newlim;
  264.       return (setrlimit (RLIMIT_FSIZE, &limit));
  265. #endif
  266.     }
  267.  
  268.     case u_MAX_BREAK_VAL:
  269. #if !defined (HAVE_RESOURCE)
  270.       if (!setting)
  271.     return (ulimit (3, 0L));
  272.       else
  273.     return ((long) -1);
  274. #else
  275.       if (!setting)
  276.     {
  277.       if (getrlimit (RLIMIT_DATA, &limit) != 0)
  278.         return ((long) -1);
  279.           return (limit.rlim_cur);
  280.     }
  281.       else
  282.     {
  283.       getrlimit (RLIMIT_DATA, &limit);
  284.       limit.rlim_cur = newlim;
  285.       return (setrlimit (RLIMIT_DATA, &limit));
  286.     }
  287. #endif
  288.  
  289. #if defined (HAVE_RESOURCE)
  290.       /* You can't get or set the pipe size with getrlimit, so we have to
  291.          cheat.  */
  292.     case u_PIPE_SIZE:
  293.       if (setting)
  294.     {
  295.       errno = EINVAL;
  296.       return ((long) -1);
  297.     }
  298.       return (pipesize ());
  299.  
  300.     case u_CORE_FILE_SIZE:
  301.       if (!setting)
  302.     {
  303.       if (getrlimit (RLIMIT_CORE, &limit) != 0)
  304.         return ((long) -1);
  305.       return (limit.rlim_cur);
  306.     }
  307.       else
  308.     {
  309.       getrlimit (RLIMIT_CORE, &limit);
  310.       limit.rlim_cur = newlim;
  311.       return (setrlimit (RLIMIT_CORE, &limit));
  312.     }
  313.  
  314.     case u_DATA_SEG_SIZE:
  315.       if (!setting)
  316.     {
  317.       if (getrlimit (RLIMIT_DATA, &limit) != 0)
  318.         return (long) -1;
  319.       return (limit.rlim_cur);
  320.     }
  321.       else
  322.     {
  323.       getrlimit (RLIMIT_DATA, &limit);
  324.       limit.rlim_cur = newlim;
  325.       return (setrlimit (RLIMIT_DATA, &limit));
  326.     }
  327.  
  328.     case u_PHYS_MEM_SIZE:
  329.       if (!setting)
  330.     {
  331.       if (getrlimit (RLIMIT_RSS, &limit) != 0)
  332.         return ((long) -1);
  333.       return (limit.rlim_cur);
  334.     }
  335.       else
  336.     {
  337.       getrlimit (RLIMIT_RSS, &limit);
  338.       limit.rlim_cur = newlim;
  339.       return (setrlimit (RLIMIT_RSS, &limit));
  340.     }
  341.  
  342.     case u_CPU_TIME_LIMIT:
  343.       if (!setting)
  344.     {
  345.       if (getrlimit (RLIMIT_CPU, &limit) != 0)
  346.         return ((long) -1);
  347.       return (limit.rlim_cur);
  348.     }
  349.       else
  350.     {
  351.       getrlimit (RLIMIT_CPU, &limit);
  352.       limit.rlim_cur = newlim;
  353.       return (setrlimit (RLIMIT_CPU, &limit));
  354.     }
  355.  
  356.     case u_STACK_SIZE:
  357.       if (!setting)
  358.     {
  359.       if (getrlimit (RLIMIT_STACK, &limit) != 0)
  360.         return ((long) -1);
  361.       return (limit.rlim_cur);
  362.     }
  363.       else
  364.     {
  365.       getrlimit (RLIMIT_STACK, &limit);
  366.       limit.rlim_cur = newlim;
  367.       return (setrlimit (RLIMIT_STACK, &limit));
  368.     }
  369.  
  370.     case u_NUM_OPEN_FILES:
  371.       if (setting)
  372.     {
  373. #if defined (RLIMIT_NOFILE)
  374.       getrlimit (RLIMIT_NOFILE, &limit);
  375.       limit.rlim_cur = newlim;
  376.       return (setrlimit (RLIMIT_NOFILE, &limit));
  377. #else /* !RLIMIT_NOFILE */
  378.       errno = EINVAL;
  379.       return ((long) -1);
  380. #endif /* !RLIMIT_NOFILE */
  381.     }
  382.       else
  383.     return ((long) getdtablesize ());
  384.  
  385. #endif /* HAVE_RESOURCE */
  386.  
  387.     default:
  388.       errno = EINVAL;
  389.       return ((long) -1);
  390.     }
  391. }
  392.  
  393. #include "pipesize.h"
  394.  
  395. static long
  396. pipesize ()
  397. {
  398. #if defined (PIPE_BUF)
  399.       /* This is defined on Posix systems. */
  400.       return ((long) PIPE_BUF);
  401. #else
  402. #  if defined (PIPESIZE)
  403.       /* This is defined by running a program from the Makefile. */
  404.       return ((long) PIPESIZE);
  405. #  else
  406.  
  407.       errno = EINVAL;
  408.       return ((long) -1);
  409. #  endif /* PIPESIZE */
  410. #endif /* PIPE_BUF */
  411. }
  412.  
  413. #if defined (HAVE_RESOURCE)
  414.  
  415. #if !defined (RLIM_NLIMITS)
  416. #define RLIM_NLIMITS 6        /* Number of resource limits. */
  417. #endif
  418.  
  419. typedef struct {
  420.   int  parameter;        /* Parameter to pass to getrlimit (). */
  421.   int  block_factor;        /* Blocking factor for specific limit. */
  422.   char *description;        /* Descriptive string to output. */
  423. } BSD_RESOURCE_LIMITS;
  424.  
  425. BSD_RESOURCE_LIMITS limits[RLIM_NLIMITS + 1] = {
  426.   { RLIMIT_CPU,      1, "cpu time (seconds)" },
  427.   { RLIMIT_RSS,   1024, "max memory size (kbytes)" },
  428.   { RLIMIT_DATA,  1024, "data seg size (kbytes)" },
  429.   { RLIMIT_STACK, 1024, "stack size (kbytes)" },
  430.   { RLIMIT_FSIZE, 1024, "file size (blocks)" },
  431.   { RLIMIT_CORE,  1024, "core file size (blocks)" },
  432.   { 0, 0, (char *)NULL }
  433. };
  434.  
  435. print_all_limits ()
  436. {
  437.   register int i;
  438.   struct rlimit rl;
  439.   long limit;
  440.  
  441.   for (i = 0; i < RLIM_NLIMITS && limits[i].description; i++)
  442.     {
  443.       getrlimit (limits[i].parameter, &rl);
  444.       limit = rl.rlim_cur;
  445.       printf ("%-25s", limits[i].description);
  446.       if (limit == RLIM_INFINITY)
  447.     printf ("unlimited\n");
  448.       else
  449.     printf ("%ld\n", limit / limits[i].block_factor);
  450.     }
  451.   printf ("%-25s%ld\n", "pipe size (512 bytes)", (pipesize () / 512));
  452.   printf ("%-25s%ld\n", "open files", getdtablesize ());
  453. }
  454.  
  455. #endif /* HAVE_RESOURCE */
  456.